using UnityEngine;
using System.Collections.Generic;

public class FloorManager : Singleton<FloorManager>
{
	public Tile[,] tiles;
	public List<Interactive> interactives;

	private void Awake()
	{
		LoadTiles();
		Character.actionEnded += CharacterActionEnded;
	}

	private void OnDestroy()
	{
		Character.actionEnded -= CharacterActionEnded;
	}

	private void LoadTiles()
	{
		Tile[] allTiles = GameObject.FindObjectsOfType<Tile>();
		
		int highestX = 0;
		int highestY = 0;
		Vector3 temp;
		foreach (Tile tile in allTiles)
		{
			temp = tile.transform.position;
			if (temp.x > highestX)
			{
				highestX = (int)temp.x;
			}
			if (temp.y > highestY)
			{
				highestY = (int)temp.y;
			}
		}
		
		tiles = new Tile[highestX + 1, highestY + 1];
		foreach (Tile tile in allTiles)
		{
			temp = tile.transform.position;
			tiles[(int)temp.x, (int)temp.y] = tile;
		}
	}
	
	private void CharacterActionEnded()
	{
		if (InitiativeManager.Instance.current is Player)
		{
			Tile center = GetTile(InitiativeManager.Instance.current.transform.position);
			List<Tile> area = Area.VisibleArea(center);
			foreach (Interactive inter in interactives)
			{
				if (area.Contains(inter.currentTile))
				{
					if (inter.ActivateInteractive())
					{
						Debug.Log("Interactive Found " + inter);
					}
				}
			}
		}
	}
	
	public void RegisterInteractive(Interactive _inter)
	{
		if (!(_inter is Tile))
		{
			interactives.Add(_inter);
		}
	}
	
	public void UnregisterInteractive(Interactive _inter)
	{
		if (interactives.Contains(_inter))
		{
			interactives.Remove(_inter);
		}
	}

	public void SpawnInteractive(InteractiveInfo _info, Transform _spawn)
	{
		Interactive obj = SpawnGeneric(_info, _spawn).GetComponent<Interactive>();
		obj.Init(_info.Clone());
	}
	
	private GameObject SpawnGeneric(InteractiveInfo _info, Transform _spawn)
	{
		GameObject obj = Instantiate(_info.prefab) as GameObject;
		obj.transform.parent = _spawn.parent;
		obj.transform.position = _spawn.position;
		return obj;
	}
	
	public void DeactivateInteractives()
	{
		foreach (Interactive inter in interactives)
		{
			inter.DeactivateAsSelect();
		}
	}

	public List<Interactive> GetInteractives<T>() where T : Interactive
	{
		List<Interactive> results = new List<Interactive>();
		foreach (Interactive inter in interactives)
		{
			if (inter is T)
			{
				results.Add(inter);
			}
		}

		return results;
	}

	public List<Interactive> TileInArea(Interactive.ActionType _type, Tile _tile)
	{
		List<Interactive> result = new List<Interactive>();
		foreach (Interactive inter in interactives)
		{
			if (inter.actionType == _type && inter.selectArea.Contains(_tile))
			{
				result.Add(inter);
			}
		}

		return result;
	}

	/// <summary>
	/// Function to get all interactives inside and area
	/// </summary>
	/// <returns>Returns a dictionary of interactives and the tiles that are both in the interactives accessArea and the area.</returns>
	/// <param name="_area">Area of tiles.</param>
	/// <param name="_type">The action type that the interactive refers to.</param>
	public Dictionary<Interactive, List<Tile>> InteractivesInArea(List<Tile> _area, Interactive.ActionType _type)
	{
		Dictionary<Interactive, List<Tile>> all = new Dictionary<Interactive, List<Tile>>();
		List<Tile> tiles = new List<Tile>();
		foreach (Interactive inter in interactives)
		{
			if (inter.actionType == _type)
			{
				tiles = new List<Tile>();
				foreach (Tile tile in inter.selectArea)
				{
					if (_area.Contains(tile))
					{
						tiles.Add(tile);
					}
				}

				if (tiles.Count > 0)
				{
					all.Add(inter, tiles);
				}
			}
		}

		return all;
	}
	
	public Tile GetTile(int _x, int _y)
	{
		if (_x >= 0 && _x < tiles.GetLength(0) && _y >= 0 && _y < tiles.GetLength(1))
		{
			return tiles[_x, _y];
		}
		else
		{
			return null;
		}
	}
	
	public Tile GetTile(Vector3 _position)
	{
		int x = (int)Mathf.RoundToInt(_position.x);
		int y = (int)Mathf.RoundToInt(_position.y);
		return GetTile(x, y);
	}
}
